package chexuan.game.service.event;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import chexuan.game.constant.event.EnumEventType;
import chexuan.game.interfaces.common.InterfaceEventListener;
import chexuan.game.interfaces.service.EnumService;
import chexuan.game.interfaces.service.InterfaceEventService;

public class EventService implements InterfaceEventService {

	private static EventService instance = null;
	private final Map<EnumEventType, List<InterfaceEventListener>> lookup;

	public static synchronized EventService getInstance() {
		if (null == instance) {
			instance = new EventService();
		}

		return instance;
	}

	private EventService() {
		lookup = new HashMap<EnumEventType, List<InterfaceEventListener>>();
	}

	@Override
	public EnumService getServiceType() {
		return EnumService.EVENT_SERVICE;
	}

	@Override
	public void initialize() {

	}

	@Override
	public void destroy() {
	}

	@Override
	public EnumService[] getDependencyServices() {
		return new EnumService[] { EnumService.LOG_SERVICE,
				EnumService.TASK_SERVICE, EnumService.DB_SERVICE };
	}

	@Override
	public void register(EnumEventType[] eventTypes,
			InterfaceEventListener eventListener) {
		if (null == eventTypes) {
			return;
		}

		for (EnumEventType type : eventTypes) {
			List<InterfaceEventListener> list = lookup.get(type);
			if (null == list) {
				list = new ArrayList<InterfaceEventListener>();
				lookup.put(type, list);
			}
			list.add(eventListener);
		}
	}

	@Override
	public void unregister(EnumEventType[] eventTypes,
			InterfaceEventListener eventListener) {
		if (null == eventTypes) {
			return;
		}

		for (EnumEventType type : eventTypes) {
			List<InterfaceEventListener> list = lookup.get(type);
			if (null != list) {
				list.remove(eventListener);
			}
		}
	}

	@Override
	public void register(Object eventListener) {
		EventHandlerProxy.register(eventListener);
	}

	@Override
	public void unregister(Object eventListener) {
		EventHandlerProxy.unregister(eventListener);
	}

	@Override
	public void broadcastEvent(Event broadcastEvent) {
		List<InterfaceEventListener> list = lookup
				.get(broadcastEvent.getType());

		if (null == list || 0 == list.size()) {
			return;
		}

		list = new ArrayList<InterfaceEventListener>(list);
		for (InterfaceEventListener listener : list) {
			listener.onEvent(broadcastEvent);
			if (broadcastEvent.isCancelBubble()) {
				return;
			}
		}
	}

	@Override
	public Object queryEvent(Event event) {
		List<InterfaceEventListener> list = lookup.get(event.getType());

		if (null == list || 0 == list.size()) {
			return null;
		}

		list = new ArrayList<InterfaceEventListener>(list);
		for (InterfaceEventListener listener : list) {
			listener.onEvent(event);
			if (event.isQueryHandled()) {
				return event.getResult();
			}
		}

		return null;
	}

	@Override
	public void start() {

	}

	@Override
	public void interrupt() {
		lookup.clear();
	}
}
